package com.geely.jdemo.generic1;

import org.junit.Test;


/**
 * 为什么我们需要泛型
 * 提高可读性
 * 使 ClassCastException 这种错误在编译期就检测出来
 * 适用于多种数据类型执行相同的代码（代码复用）
 * 333333333333333333
 * 444444444444444
 * 1.泛型类和泛型接口的定义
 * <T> 泛型类型 接口 方法标识也是声明前提 里面可以是T，V，K，E比较常用，未作特殊要求
 */
public class Main {
    public int addInt(int x, int y) {
        return x + y;
    }

    public float addFloat(float x, float y) {
        return x + y;
    }

    public double addDouble(double x, double y) {
        return x + y;
    }

    // 一个泛型方法
    private static <T extends Number> double add(T a, T b) {
        return a.doubleValue() + b.doubleValue();
    }


    @Test
    public void mainTest() {
        System.out.println(addInt(1, 1));
        System.out.println(addFloat(1f, 1f));
        System.out.println(addDouble(1d, 1d));
        //我们发现，当累加的时候需求并不是单一，这时传入不同的数据类型继而重写多个方法，这样的代码显得很冗余

        //那么使用泛型就可以操作 int、float、double 类型，用一个泛型方法就实现了上面三个重载方法的功能。
        System.out.println(add(1, 2));
        System.out.println(add(1f, 2f));
        System.out.println(add(1d, 2d));

        //使用泛型类
        NormalGeneric<String> stringNormalGeneric = new NormalGeneric<String>();
        stringNormalGeneric.setData("OK");
        System.out.println(stringNormalGeneric.getData());
    }

    /**
     * 泛型类
     *
     * @param <T>
     */
    static class NormalGeneric<T> {
        private T data;

        public NormalGeneric(T data) {
            this.data = data;
        }

        public NormalGeneric() {
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }
    }


    /**
     * 泛型接口
     */
    public interface IGeneric<T> {
        T next();
    }

    /**
     * 实现泛型接口 传入任意类型
     *
     * @param <T>
     */
    class ImplGeneric1<T> implements IGeneric<T> {

        @Override
        public T next() {
            return null;
        }
    }

    /**
     * 实现泛型接口 传入String指定类型
     *
     * @param <T>
     */
    class ImplGeneric2<T> implements IGeneric<String> {

        @Override
        public String next() {
            return null;
        }
    }
}

